/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __ISCENE_H__
#define __ISCENE_H__

#pragma once

#include "StdAfx.h"

#include "IRenderer.h"
#include "IInputHandler.h"
#include "sg/SceneNode.h"
#include "gui/Component.h"
#include "ResourceFactory.h"

/**
 * An abstract class for scene content
 */
class DLL_EXPORT IScene
{
public:
	IScene(void);
	virtual ~IScene(void);

	/// Initialize the scene and all it's content
	virtual bool init();

	/// Updates all the objects in the scene. dt is in seconds
	virtual void update(double dt) {};
	
	/// Draws the scene
	virtual void draw() {};

	/// Draws 2D elements on screen
	virtual void draw2DElements();

	/// Called upon destruction of the object
	virtual void destroy();

	/// Processes the key down event from the windows message proc
	virtual void processKeyDown(WPARAM wParam, LPARAM lParam);

	/// Processes the key up event from the windows message proc
	virtual void processKeyUp(WPARAM wParam, LPARAM lParam);

	/// This one is important. All others are deprecated.
	virtual void processKey(UINT msg, WPARAM wParam, LPARAM lParam);

	/// Process any keys 
	virtual void processKeys();

	/// Process mouse movement (absolute positions)
	virtual void processMouse(int mx, int my, int mz, int button = -1);

	/// Process mouse movement (relative positions)
	virtual void processMouseMotion(int relx, int rely, int relz, int button = -1);

	/// Process joystick movement (relative positions)
	virtual void processJoystickMotion(const math::Vector2f &axis1, const math::Vector2f &axis2) {};

	/// Process joystick buttons 
	virtual void processJoystickButtons(BYTE *buttons) {};
	
	/// Returns the reference to the initialized rendering interface
	virtual IRenderer* getRenderer();

	/// Returns the inputhandler that is loaded. Should be used inside processKeys
	virtual IInputHandler* getInputHandler();

	/// Enables showing of the mouse. A mouse pointer should be loaded first using IRenderer::setMousePointer()
	void showMouse(bool value, bool center = false);

	/// Indicates if a mouse pointer is currently visible
	const bool isMouseShown() const;

	/// Returns the root of the scene graph used for rendering
	sg::SceneNode* getRoot();

	/// Returns the root of the GUI component
	gui::Component* getGUIRoot() const;

	/// Called by the core's rendering loop. Please use the draw() function instead
	virtual void drawScene();

	/// Indicates if the scene is initialized. Set to true after loading the scene and running init()
	bool isInitialized() const;
	void setInitialized(bool value);

	/// Draws a preload image
	void drawPreload();
	void setPreloadImage(ITexture* texture);

	virtual void release() {};
	virtual void restore() {};

	virtual bool isHDRScene() const { return false; }

	/// Adds a light to the scene. Lights must be in world coordinates
	void addLight(ILight *light);
	void clearLights();

	/// Returns a list of all the lights in the scene
	std::list<ILight*>* getLights();
	std::list<ILight*>* getVisibleLights();

	ILight* getLight(int pos);

	void getCurrentMouseState( int state[4]);

	void setGuiRoot( gui::Component *comp);

	/// Draw the light sources as spheres for debug purpose
	void debugDrawLights();

protected:
	/// Called before drawing the scene. 
	virtual bool preDraw();

	/// Called after drawing the scene to present it on screen. 
	/// When overwriting this function, call IScene::postDraw() last!
	virtual void postDraw();

	IRenderer      *pRenderer;		///< A reference to the renderer
	IInputHandler  *pInputHandler;	///< A reference to the IInputHandler
	sg::SceneNode  *pRootNode;		///< The scene graph root
	gui::Component *pGuiRoot;		///< The GUI root

	bool            bInitialized;
	bool            bshowMouse;
	bool            bCenterMouse;
	bool            bShowFPS;
	int             iMousePosX;
	int             iMousePosY;
	int             iMousePosZ;
	int             iLastMouseButton; // 21.03.07: ist immer -1 ???

	IFont	 *debuginfo;

	std::vector<sg::SceneNode*> m_vVisibleObjects;
	std::list<ILight*>          m_vLightList;
	std::list<ILight*>          m_vVisibleLights;

	ITexture *pPreloadImage;

	void updateVisibleLights(ICamera* camera);
};


DLL_EXPORT
IScene* coreGetScene();


#endif
